package com.itheima.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.itheima.common.DefaultException;
import com.itheima.config.ThreadPoolConfig;
import com.itheima.convert.CommentConvert;
import com.itheima.dto.CommentDto;
import com.itheima.entity.Comment;
import com.itheima.entity.Message;
import com.itheima.entity.User;
import com.itheima.enums.OrganizationEnum;
import com.itheima.mapper.CommentMapper;
import com.itheima.service.CommentService;
import com.itheima.service.MessageService;
import com.itheima.service.SensitiveWordFilterService;
import com.itheima.service.UserService;
import com.itheima.utils.CheckUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.comment.CommentChildVo;
import com.itheima.vo.comment.CommentParentVo;
import io.jsonwebtoken.lang.Collections;
import net.sf.jsqlparser.statement.insert.InsertModifierPriority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Semaphore;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 51585
 * @description 针对表【comment】的数据库操作Service实现
 * @createDate 2022-10-21 14:35:48
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
        implements CommentService {
    @Resource
    private UserService userService;
    @Resource
    private CommentConvert commentConvert;
    @Resource
    private MessageService messageService;
    @Resource
    private SensitiveWordFilterService sensitiveWordFilterService;
    @Resource
    private CommentMapper commentMapper;

    @Override
    public String sendComment(CommentDto commentDto) throws Exception {
        String userId = CheckUtil.checkLogin();
        filterCommentDto(commentDto);
        Integer count = messageService.lambdaQuery()
                .eq(Message::getId, commentDto.getMessageId())
                .count();
        checkCount(count);
        Comment comment = commentConvert.commentDtoToComment(commentDto);
        comment.setCreatedAt(LocalDateTime.now());
        comment.setUserId(userId);
        this.save(comment);
        if (comment.getParentCommentId() != 0) {
            Comment parentComment = this.getById(comment.getParentCommentId());
            Optional.ofNullable(parentComment).orElseThrow(() -> new DefaultException("该评论已删除，请勿评论"));
            parentComment.setIsChild(0);
            this.updateById(parentComment);
        }
        return "发布评论成功";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String deleteComment(Integer commentId) throws Exception {
        String userId = CheckUtil.checkLogin();
//        String userId = "19251104252";
        Comment comment = this.getById(commentId);
        Optional.ofNullable(comment).orElseThrow(() -> new DefaultException("该评论已经删除，请勿重复操作"));
        User user = userService.getById(userId);
        if (!comment.getUserId().equals(userId)
                && user.getOrganizationId() != OrganizationEnum.administrators.getOrganizationId()
                && user.getOrganizationId() != OrganizationEnum.school.getOrganizationId()) {
            throw new DefaultException("没有权限");
        }
        if (comment.getParentCommentId() == 0) {
            deleteAllComment(comment);
            return "评论删除成功";
        }
        this.lambdaUpdate()
                .eq(Comment::getId, commentId)
                .set(Comment::getContent, "该评论已删除")
                .set(Comment::getDeletedAt, LocalDateTime.now())
                .update();
        if (comment.getIsChild() == 1) {
            Integer parentCommentId = comment.getParentCommentId();

            List<Comment> list = this.lambdaQuery()
                    .eq(Comment::getParentCommentId, parentCommentId)
                    .list();
            if (list.isEmpty()) {
                this.lambdaUpdate()
                        .eq(Comment::getId, parentCommentId)
                        .set(Comment::getIsChild, 1)
                        .update();
            }
        }
        return "评论删除成功";
    }

    @Override
    public List<CommentVo> showComment(Integer messageId) {
        List<Comment> list = this.lambdaQuery()
                .eq(Comment::getMessageId, messageId)
                .eq(Comment::getParentCommentId, 0)
                .list();
        List<CommentVo> collect = list.stream().map(k -> {
            CommentVo commentVo = commentConvert.commentToCommentVo(k);
            supplyTime(commentVo, k);
            if (commentVo.getIsChild() == 1) {
                return commentVo;
            }
            CommentVo res = getChild(commentVo);
            return res;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<CommentParentVo> parentComment(Integer messageId) {
        List<Comment> list = this.lambdaQuery()
                .eq(Comment::getMessageId, messageId)
                .eq(Comment::getParentCommentId, 0)
                .isNull(Comment::getDeletedAt)
                .list();
        if (Collections.isEmpty(list)) {
            return null;
        }
        List<CommentParentVo> commentParentVos = commentConvert.toCommentParentVo(list);
        List<String> collect = commentParentVos.stream().map(CommentParentVo::getUserId).collect(Collectors.toList());
        List<User> userList = userService.lambdaQuery()
                .select(User::getId, User::getName, User::getImageUrl)
                .in(User::getId, collect)
                .isNull(User::getDeletedAt)
                .list();
        Map<String, User> map = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
        commentParentVos.forEach(k -> {
            if (map.containsKey(k.getUserId())) {
                k.setUserName(map.get(k.getUserId()).getName());
                k.setImageUrl(map.get(k.getUserId()).getImageUrl());
            }
            List<Comment> list1 = this.lambdaQuery()
                    .select(Comment::getId)
                    .eq(Comment::getParentCommentId, k.getId())
                    .list();
            if (CollectionUtils.isEmpty(list1)) {
                k.setIsChild(1);
            }
        });
        return commentParentVos;
    }

    @Override
    public List<CommentChildVo> childComment(Integer commentId) throws DefaultException {
        Comment comment = this.getById(commentId);
        List<Comment> list = commentMapper.listComment(comment.getMessageId());
        if (list.size() < 2) {
            throw new DefaultException("当前评论没有回复");
        }
        Map<Integer, List<Comment>> map = list.stream()
                .collect(Collectors.groupingBy(Comment::getParentCommentId, Collectors.toList()));
        List<CommentChildVo> res = new ArrayList<>();
        supplyComment(res, comment, map);
        supplyUserMessage(res);
        return res;
    }


    /**
     * 删除所有comment（删除父评论时，其下的所有评论都删除）
     *
     * @param comment 评论实体
     */
    public void deleteAllComment(Comment comment) {
        List<Integer> list = new ArrayList<>();
        list.add(comment.getId());
        summaryDeleteId(list, comment);
        List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
        this.lambdaUpdate()
                .set(Comment::getDeletedAt, LocalDateTime.now())
                .in(Comment::getId, collect)
                .update();
    }

    public void summaryDeleteId(List<Integer> list, Comment comment) {
        if (comment.getIsChild() == 1) {
            list.add(comment.getId());
            return;
        }
        List<Comment> commentList = this.lambdaQuery()
                .select(Comment::getId, Comment::getParentCommentId, Comment::getIsChild)
                .eq(Comment::getParentCommentId, comment.getId())
                .list();
        List<Integer> collect = commentList.stream().map(Comment::getId).collect(Collectors.toList());
        list.addAll(collect);
        commentList.forEach(k -> {
            summaryDeleteId(list, k);
        });
    }

    /**
     * 补充评论
     *
     * @param res           子评论Vo
     * @param parentComment 评论实体
     * @param map           评论map
     */
    public void supplyComment(List<CommentChildVo> res, Comment parentComment, Map<Integer, List<Comment>> map) {
        List<Comment> list = map.get(parentComment.getId());
        Optional.ofNullable(list).ifPresent(k -> {
            k.forEach(mid -> {
                CommentChildVo commentChildVo = commentConvert.toCommentChildVo(parentComment, mid);
                commentChildVo.setReplyUserId(parentComment.getUserId());
                commentChildVo.setReplyContent(parentComment.getContent());
                res.add(commentChildVo);
                supplyComment(res, mid, map);
            });
        });
    }

    /**
     * 补充用户信息
     *
     * @param res 子评论Vo
     */
    public void supplyUserMessage(List<CommentChildVo> res) {
        List<String> collect = res.stream().map(CommentChildVo::getUserId).collect(Collectors.toList());
        List<String> collect1 = res.stream().map(CommentChildVo::getReplyUserId).collect(Collectors.toList());
        collect.addAll(collect1);
        List<String> userIdList = collect.stream().distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(userIdList)) {
            return;
        }
        List<User> list = userService.lambdaQuery()
                .select(User::getId, User::getName, User::getImageUrl)
                .in(User::getId, userIdList)
                .isNull(User::getDeletedAt)
                .list();

        Map<String, User> map = list.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        res.forEach(k -> {
            Optional.ofNullable(map.get(k.getUserId())).ifPresent(mid -> {
                k.setUserName(mid.getName());
                k.setImageUrl(mid.getImageUrl());
            });
            Optional.ofNullable(map.get(k.getReplyUserId())).ifPresent(mid -> {
                k.setReplyUserName(mid.getName());
            });
        });
    }

    /**
     * 获取子评论
     *
     * @param commentVo
     * @return
     */
    public CommentVo getChild(CommentVo commentVo) {
        if (commentVo.getIsChild() == 1) {
            return null;
        }
        List<Comment> list = this.lambdaQuery()
                .eq(Comment::getParentCommentId, commentVo.getId())
                .list();
        List<CommentVo> collect = list.stream().map(comment -> {
            CommentVo commentMid = commentConvert.commentToCommentVo(comment);
            supplyTime(commentMid, comment);
            getChild(commentMid);
            return commentMid;
        }).collect(Collectors.toList());

        commentVo.setCommentVos(collect);
        return commentVo;
    }

    public void supplyTime(CommentVo commentVo, Comment comment) {
        if (StringUtils.isEmpty(comment.getDeletedAt())) {
            if (StringUtils.isEmpty(comment.getUpdatedAt())) {
                commentVo.setTime(comment.getCreatedAt());
            } else {
                commentVo.setTime(comment.getUpdatedAt());
            }
        } else {
            commentVo.setTime(comment.getDeletedAt());
        }
    }

    /**
     * 判断数据库是否已经有对应的message
     * 有则返回true，没有返回false
     *
     * @param count
     * @return
     */
    public void checkCount(int count) throws DefaultException {
        if (count < 1) {
            throw new DefaultException("没有该条信息");
        }
    }

    /**
     * 过滤CommentDto 中的敏感信息
     *
     * @param commentDto
     */
    public void filterCommentDto(CommentDto commentDto) throws JsonProcessingException {
        commentDto.setContent(sensitiveWordFilterService.filter(commentDto.getContent()));
    }



}




